package mylab.starters.mybatis.support.mixedSource.impl;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.dynamic.datasource.provider.AbstractJdbcDataSourceProvider;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import mylab.starters.mybatis.config.DbProperties;
import mylab.starters.mybatis.support.mixedSource.TenantDataSourceLoader;
import mylab.starters.mybatis.support.mixedSource.TenantDataSourceService;
import mylab.starters.mybatis.utils.QueryUtil;
import org.springframework.beans.BeanUtils;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Map;
import java.util.stream.Collectors;

import static mylab.base.constants.DbConst.*;


/**
 * 在租户表中存储该租户的独立数据源配置
 * 默认租户表:sys_tenant
 * 默认数据源字段：ds_config
 */
@Slf4j
public class TenantDataSourceJdbcLoader extends AbstractJdbcDataSourceProvider implements TenantDataSourceLoader {
    private DbProperties dbProperties;

    private Map<String, DataSourceProperty> map;

    public TenantDataSourceJdbcLoader(DataSourceProperty master, DbProperties dbProperties) {
        super(master.getDriverClassName(), master.getUrl(), master.getUsername(), master.getPassword());
        this.dbProperties = dbProperties;
    }

    @Override
    public Map<String, DataSourceProperty> getAll() {
        if (map == null || map.isEmpty()) {
            loadDataSources();
        }
        return map;
    }

    @Override
    public DataSourceProperty getByTenantId(Long tenantId) {
        String dsName = TenantDataSourceService.getTenantDsName(String.valueOf(tenantId));
        return getAll().get(dsName);
    }

    @Override
    protected Map<String, DataSourceProperty> executeStmt(Statement statement) throws SQLException {
        Assert.isTrue(existTable(statement, TENANT_TABLE_NAME), "未发现租户表:" + TENANT_TABLE_NAME);
        map = Maps.newHashMap();

        String sql = CharSequenceUtil.format("select {}, {} from {} where {} = 0",
                COLUMN_ID,
                dbProperties.getTenant().getDatasource().getDsColumn(),
                TENANT_TABLE_NAME,
                COLUMN_DELETED);

        ResultSet rs = statement.executeQuery(sql);
        String id;
        String dsName;
        String dsConfig;
        while (rs.next()) {
            id = rs.getString(COLUMN_ID);
            dsName = TenantDataSourceService.getTenantDsName(id);
            dsConfig = rs.getString(TENANT_DATASOURCE_COLUMN_NAME);

            DataSourceProperty dsProperty = new DataSourceProperty();
            BeanUtils.copyProperties(fromString(dsConfig), dsProperty);
            dsProperty.setPoolName(dsName);

            map.put(dsName, dsProperty);
        }
        rs.close();

        String names = map.keySet().stream().sorted().collect(Collectors.joining(","));
        log.info("发现租户数据源:{}", names);

        return map;
    }


    DataSourceProperty fromString(String dsConfig) {
        return JSONUtil.toBean(dsConfig, DataSourceProperty.class);
    }

    boolean existTable(Statement statement, String table) throws SQLException {
        return QueryUtil.existTable(statement, table);
    }
}
